home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v9n03.arc / CFCOMPC.ASM < prev    next >
Assembly Source File  |  1990-01-12  |  97KB  |  1,582 lines

  1.          PAGE  60,132
  2.          TITLE CFCOMPC - CHKfile Compressed file compare utility
  3. ;        SUBTTL  General program description and use of common storage
  4. ; ----------------------------------------------------------------------------;
  5. ;        CFCOMPC - Compare compressed report files created by CHKfileC        ;
  6. ; ----------------------------------------------------------------------------;
  7. ;   CFCOMPC 1.0 ■ PCDATA TOOLKIT Copyright (c) 1990 Ziff Communications Co.   ;
  8. ;                   PC Magazine ■ Wolfgang Stiller                            ;
  9. ;                                                                             ;
  10. ;-----------------------------------------------------------------------------;
  11. ; Purpose:                                                                    ;
  12. ; CFCOMPC does a high speed compare of report files created by CHKfileC.      ;
  13. ; CFCOMPC then displays which files have been changed, deleted or added       ;
  14. ; between the creation of the OLD and NEW report files.                       ;
  15. ; ----------------------------------------------------------------------------;
  16. ; Format:                                                                     ;
  17. ;                                                                             ;
  18. ; CFCOMPC OLDfile NEWfile  [/C] [/O] [/P]                                     ;
  19. ;                                                                             ;
  20. ;       Oldfile and NewFile are CHKFILEC.COM created report file.             ;
  21. ;       "/C"      Changes only - reports and checks only for changed files    ;
  22. ;                 and ignores additions or deletions from file list.          ;
  23. ;       "/O"      Only use check fields and file size for comparison. DOS time;
  24. ;                 and date stamps are not used in comparing.                  ;
  25. ;       "/P"      Pauses after each page of output if non-matches are detected.
  26. ; ----------------------------------------------------------------------------;
  27. ;Remarks:                                                                     ;
  28. ;                                                                             ;
  29. ; CFCOMPC utilizes a high speed compare algorithm tailored specifically       ;
  30. ; to comparing report files produced by CHKfileC.  It will work even if       ;
  31. ; the directories  have been sorted in a different order.  The order of       ;
  32. ; the files in the NEW and OLD files is completely independent.  If the       ;
  33. ; order is the same, (which is  usually the case) CFCOMPC runs the            ;
  34. ; fastest.  CFCOMPC writes to DOS standard output, so that its output         ;
  35. ; may be redirected to a file. "CFCOMPC A B >OUT" will compare old file       ;
  36. ; A and new file B with any differences reported on file OUT.                 ;
  37. ;                                                                             ;
  38. ; CFCOMPC will utilize the check value 1 and 2 fields to identify             ;
  39. ; certain special types of files. "Dir." will appear if the entry is a        ;
  40. ; directory.  If CHKfileC was unable to read or open the file, "Read          ;
  41. ; fail" or "Open fail" will appear in these fields.  As much other            ;
  42. ; information will displayed as possible.                                     ;
  43. ;                                                                             ;
  44. ; The individual report (input) files may not be larger than 65,536           ;
  45. ; bytes.  This size allows up to 2620 file entries in each report             ;
  46. ; (input) file. To compare this many entries in each file, CFCOMPC            ;
  47. ; requires that at least 133,000 bytes of memory are free. CFCOMPC will       ;
  48. ; automatically adjust its memory allocation to use whatever memory is        ;
  49. ; available. For each 1000 less bytes of free memory, 20 fewer file           ;
  50. ; entries can be supported. CFCOMPC will verify the internal integrity        ;
  51. ; check data in each report file and report that the file is an invalid       ;
  52. ; type if corruption is detected.                                             ;
  53. ;                                                                             ;
  54. ; If the OLDfile is not found, CFCOMPC will report this fact and then         ;
  55. ; continue executing, treating OLDfile as if it were an empty file.           ;
  56. ;                                                                             ;
  57. ; All serious error conditions (such as a corrupted or invalid report         ;
  58. ; file) will result in an error message accompanied by a beep, a prompt       ;
  59. ; and a wait for a key press.                                                 ;
  60. ;                                                                             ;
  61. ;  CFCOMPC will return the following DOS ERRORLEVELs (decimal):               ;
  62. ;   (Higher DOS ERRORLEVELS override the lower ones)                          ;
  63. ;   128 - indicates control card syntax error                                 ;
  64. ;    20 - indicates file open or other I/O error on one of the files          ;
  65. ;    16 - indicates file(s) of invalid type for CFCOMPC or file too large     ;
  66. ;         for available memory.                                               ;
  67. ;    12 - indicates file(s) have been changed                                 ;
  68. ;     8 - indicates file(s) added and/or deleted but no files changed         ;
  69. ;     4 - indicates file(s) have probably been renamed rather than actually   ;
  70. ;         changed or deleted, since the "TOTAL==>" lines match but the files  ;
  71. ;         themselves did not.                                                 ;
  72. ;     0 - files match exactly                                                 ;
  73. ;                                                                             ;
  74. ; --------------------------------------------------------------------------  ;
  75. ;Sample output:                                                               ;
  76. ;                                                                             ;
  77. ;CFCOMPC 1.0 ■ PCDATA TOOLKIT (c) 1990 Ziff Communications Co.                ;
  78. ;PC Magazine ■ Wolfgang Stiller in directory: \ASM\EXAMPLES                   ;
  79. ;          File Name + Check Check  File    Update   Update                   ;
  80. ;          Extension:  Val1: Val2:  Size:   Date:    Time:                    ;
  81. ;          ----------   ---- ----   -----   ------   ------                   ;
  82. ;Chgd: OLD:SDOC.BAK     BC37 2709     61A6 02/09/89 00:07:54                  ;
  83. ;      NEW:SDOC.BAK     A6B4 A64F     6769 02/11/89 23:55:02                  ;
  84. ;Chgd: OLD:SDOC         BC37 2709     61A6 02/09/89 00:13:48                  ;
  85. ;      NEW:SDOC         BC37 2709     61A6 02/12/89 00:07:54                  ;
  86. ;Deleted-->OUT          1E4A 4FD5       65 02/12/89 00:10:30                  ;
  87. ;NEW Fil-->NEWOUT.TXT   1E4A 4FD5       65 02/12/89 00:10:30                  ;
  88. ;NEW Fil-->TESTDIR      Dir.               02/11/89 00:07:48                  ;
  89. ;File totals unequal                                                          ;
  90. ;                                                                             ;
  91. ;Notes: CFCOMPC displays which directory it is in when doing the compare.     ;
  92. ;       In this case, it is in directory \ASM\EXAMPLES.  Files SDOC and       ;
  93. ;       SDOC.BAK have both changed.  Even though file OUT has apparently      ;
  94. ;       been deleted and file NEWOUT.TXT has been added, it is obvious        ;
  95. ;       that file OUT has merely been renamed since the check values and      ;
  96. ;       file sizes match.  TESTDIR is the name of a directory which has       ;
  97. ;       been added.                                                           ;
  98. ; ----------------------------------------------------------------------------;
  99.  
  100. ;---------------------------------------------------------------;
  101. ; Constants:                                                    ;
  102. ;---------------------------------------------------------------;
  103. BOX               EQU  254                ;Small box character code
  104. CR                EQU  0Dh
  105. LF                EQU  0Ah
  106. CRLF              EQU  0A0Dh              ;Carriage return line feed.
  107. Rep_Rec_len       EQU  25                 ;Length of the rep (report) record
  108.                                           ;The following 2 values must be even:
  109. Rep_Key_len       EQU  12                 ;Length of the key part of rep record
  110. Rep_NonKEY_Len    EQU  12                 ;Nonkey = rec_len - (key + FT_byte)
  111. DSP_Rec_len       EQU  51                 ;Length of the DSP (Display) record
  112. Tot_Rec_len       EQU  8                  ;Length of final totals + check record
  113.  
  114.  
  115. ;---------------------------------------------------------------;
  116. ; Structures:                                                   ;
  117. ;---------------------------------------------------------------;
  118. Rep_Rec         STRUC                     ;Define structure of compresed
  119.                                           ;  report records
  120. Rep_F_Type        DB   ?                  ;Indicates if its a file(1) or dir(2)
  121.                                           ;or open err (3) or I/O error (4)
  122. Rep_F_Name        DB   12 DUP (?)         ;12 spaces reserved for filename
  123. ;     ** Note, CHK+XOR sums and FS MUST immediately follow the KEY fields **
  124. Rep_CHK_Sum       DW   ?                  ;Check value 1 (CHKsum) 16 bits
  125. Rep_XOR_Sum       DW   ?                  ;Check value 2 (XOR value) 16 bits
  126. Rep_FS_Lowr       DW   ?                  ;File size lower part of double word
  127. Rep_FS_HIr        DW   ?                  ;File size: upper prt of Double Word
  128. Rep_F_Date        DW   ?                  ;Date of last file update:
  129. Rep_F_Time        DW   ?                  ;Time of last file update
  130. Rep_Rec         ENDS
  131.  
  132.  
  133. Tot_Rec         STRUC                     ;Define structure of the final TOTALS
  134.                                           ; record
  135. TOT_CHK_Sum       DW    ?                 ;Total of all check value 1s (CHKSUM)
  136. TOT_XOR_Sum       DW    ?                 ;Combination of all check value 2s
  137. TOT_Int_XOR       DW    ?                 ;Internal chk dif of this file itself
  138. TOT_Int_CHK       DW    ?                 ;Internal XOR check value (this file)
  139. Tot_Rec         ENDS
  140.  
  141. CSEG    SEGMENT
  142.         ASSUME  CS:CSEG, DS:CSEG, ES:Nothing, SS:CSEG
  143.         SUBTTL  Main program
  144. ;******************************************************************************;
  145. ;**   Main program begins here -CFCOMPC-                                     **;
  146. ;******************************************************************************;
  147.         ORG     100h                      ; This is a COM type program
  148. CFCOMPC:
  149.         CALL    Parse_parms_Open_Files    ;Parse cmdline paramters + open files
  150.  
  151.         MOV     BX,offset Buffer_Area+200 ;locate stack down in prog storage
  152.         MOV     SP,BX                     ;Stack of 200 bytes
  153.  
  154.         CALL    Allocate_Memory           ;Allocate memory for file buffers
  155.                                           ;and release other unused memory.
  156.                                           ;ES will point to start of allco mem
  157.  
  158.         CALL    Read_and_Validate_Files   ;Validate that both files are
  159.                                           ;readable and of right type to read
  160.                                           ;DS is now addressing DATA SEG (DS=CS)
  161.         XOR     BX,BX                     ;Zero highest error level variable(BL)
  162.         MOV     BH,Page_mode              ;Load line counter + pagemode flag
  163.                                           ;   =FFh for no paging
  164.         CALL    Compare_Files             ;Compare OLD file with NEW file and
  165.                                           ; determine changed or deleted recs
  166.         CALL    Scan_for_Additions        ;Look for records left on NEW file
  167.         CALL    Compare_totals            ;Check if TOT_REC CHK + XOR fields =
  168.         CMP     BH,0FFh                   ;See if page mode is off (= FFh)
  169.         JE      Normal_termination        ;   IF turned off, skip page control
  170.         OR      BL,BL                     ;See if changes detected (BL not = 0)
  171.         JE      Normal_termination        ;   If no changes, then terminate
  172.         CALL    Page_Wait                 ;   otherwise pause for user to read
  173.                                           ;     the display.
  174. Normal_termination:
  175.         MOV     AL,BL                     ;Load error level for termination
  176.         MOV     AH,4Ch                    ;   terminate
  177.         INT     21h
  178.  
  179. ;---------------------------------------------------------------------------;
  180. ; Compare files   - will compare OLD and NEW file (25 character records)    ;
  181. ;---------------------------------------------------------------------------;
  182. ; Register conventions:                                                     ;
  183. ;    DS=Segment register for OLD SEG      ES=Segment of current NEW rec     ;
  184. ;    SI=offset of current OLD rec         DI=offset of current NEW rec      ;
  185. ;    CX=number of OLD recs left to proc.  BP=offset of last NEW rec         ;
  186. ;    BL=highest code for DOS errorlevel   BH=line counter (for /P option)   ;
  187. ;---------------------------------------------------------------------------;
  188. ; Entry:                                                                    ;
  189. ;  Both files have been read into file buffers and validated                ;
  190. ;  DS is segment register for DATA(=CS); ES is segment regst for NEW file.  ;
  191. ; Exit:                                                                     ;
  192. ;   Reports will be written to STD output show all file changes + additions.;
  193. ;   All matched NEW file entries have 1st byte of filename zeroed.          ;
  194. ;   Reports have been written to Std output, on discrepancies so far.       ;
  195. ;   BL = 12 if changes, =8 if added/deleted files, and =0 for no changes    ;
  196. ;---------------------------------------------------------------------------;
  197. Compare_early_exit:
  198.         RET
  199. Compare_Files:
  200.         XOR     DI,DI                     ;1st record address of NEW file = zero
  201.         MOV     SI,DI                     ;1st record address of OLD file = zero
  202.         MOV     CX,OLD_Rec_count          ;number of records on OLD file
  203.         JCXZ    Compare_early_exit        ;If no files in OLD directory: EXIT
  204.         MOV     BP,NEW_End_Of_File        ;Offset past last rec on NEW file
  205.         MOV     AX,ES                     ;NEW file SEGment
  206.         SUB     AX,File_Size_PARAs        ;AX is segment address for OLD file
  207.         MOV     DS,AX                     ;DS = SEG reg for OLD file
  208.         SUB     DI,Rep_rec_len            ;Point to -1 record on NEW file
  209.         SUB     SI,Rep_rec_len            ;Point to record -1 on OLD file
  210.  
  211. Compare_Next:                             ;Main compare loop - get next NEW+OLD
  212.         ADD     DI,Rep_rec_len            ;Advance to next NEW record
  213.  
  214. Check_Next_OLD_REC:                       ;Secondary compare loop: next OLD rec
  215.         ADD     SI,Rep_rec_len            ;Advance to next OLD rec
  216.         CMP     DI,BP                     ;Compare offset of this new rec + EOF
  217.         JB      Compare_Keys              ;  If we are not past EOF on this rec
  218.         CALL    Displ_Deleted_Msg         ;  Else remaining old recs are deletd
  219.         LOOP    Check_Next_OLD_REC        ;Continue reporting deleted old recs
  220.         RET                               ;All done with main file compare
  221.  
  222. Compare_Keys:
  223. ; Compare File keys  (1st 12 characters of each record)
  224.         MOV     DX,CX                     ;Save a copy of CX (# of old recs)
  225.         MOV     CX,Rep_Key_len/2          ;Compare # words in key (must be even)
  226.         PUSH    DI                        ;Save current NEW rec loc
  227.         PUSH    SI                        ;Save current OLD rec loc
  228.         INC     SI                        ;Skip over file type byte
  229.         INC     DI                        ;Skip it in NEW rec too
  230.         REPE    CMPSW                     ;Do compare
  231.         JNE     Find_Matching_NEW_Rec     ;if not =, Scan NEW file for a match
  232.  
  233. ; Now compare the actual records (keys already match):
  234. ;       ***Warning*** the length field of following instr may be patched by /O
  235. PATCH1: MOV     CX,(Rep_NonKEY_Len)/2     ;Compare remainder of record 6 words
  236.         REPE    CMPSW                     ;Do compare
  237.         POP     SI                        ;Point back to start of this OLD rec
  238.         POP     DI                        ;Point back to start of this NEW rec
  239.         JE      Good_compare              ;If the records match
  240.         CALL    Displ_Changed_Msg         ;Report detection of changed record
  241. Good_compare:
  242. ;       Now zero out the 1st byte of the matched NEW file record:
  243.         XOR     AX,AX                     ;Zeros to store on key of record
  244.         STOSB                             ;Zero 1st byte
  245.         DEC     DI                        ;Point back to start of NEW rec
  246.         MOV     CX,DX                     ;Restore OLD file recs remaining count
  247.         LOOP    Compare_Next              ;Go check next record on OLD+NEW files
  248.         RET                               ;All done with COMPARE_FILE
  249.  
  250. ;-------------------------------------------;
  251. ;Search NEW file records for a matching key ;
  252. ;-------------------------------------------;
  253. Find_Matching_NEW_Rec:                    ;Search NEW file to match OLD file rec
  254.         POP     SI                        ;Restore pointer to current record
  255.         POP     DI                        ;Restore pointer to current record
  256.         SUB     SP,2                      ;Leave current NEW rec pointer on stak
  257.  
  258. Continue_NEW_File_Search:
  259.         ADD     DI,Rep_rec_len            ;Next record on NEW file
  260.                                           ;Are we at End Of File (EOF) ?
  261.         CMP     DI,BP                     ;Compare CURRENT NEW rec with EOF
  262.         JB      Compare_Keys_NEW_Rec      ;IF not EOF, go compare the keys
  263. ;  We are at END Of File (EOF) on NEW file on this search, so report deleted rec
  264.         CALL    Displ_Deleted_Msg         ;Report that rec from OLD file deleted
  265.         POP     DI                        ;point to last CURRENT rec on NEW file
  266.         MOV     CX,DX                     ;Restore OLD file recs remaining count
  267.         LOOP    Check_Next_OLD_rec        ;Go check next record on OLD file
  268.         RET                               ;All done with COMPARE_FILE
  269. Compare_Keys_NEW_Rec:                     ; (1st 13 characters of each record)
  270.         MOV     CX,Rep_Key_len/2          ;Compare # words in key (must be even)
  271.         PUSH    DI                        ;Save current NEW rec loc
  272.         PUSH    SI                        ;Save current OLD rec loc
  273.         INC     SI                        ;Skip over file type byte
  274.         INC     DI                        ;Skip it in NEW rec too
  275.         REPE    CMPSW                     ;Do compare
  276.         JE      Match_rest_of_NEW_Rec     ;  If keys =, check the records
  277.                                           ;  Else go check next NEW rec
  278.         POP     SI                        ;Point back to start of this OLD rec
  279.         POP     DI                        ;Point back to start of this NEW rec
  280.         JMP     SHORT Continue_NEW_File_Search ;Go try next NEW file rec
  281.  
  282. Match_rest_of_NEW_Rec:                    ;NEW file scan has found matching keys
  283. ;       Now compare the actual records (keys already match):
  284. ;       ***Warning*** the length field of following instr may be patched by /O
  285. PATCH2: MOV     CX,(Rep_NonKEY_Len)/2     ;Compare remainder of record: 6 words
  286.         REPE    CMPSW                     ;Do compare
  287.         POP     SI                        ;Point back to start of this OLD rec
  288.         POP     DI                        ;Point back to start of this NEW rec
  289.         JE      Found_matching_NEW_rec    ;If the records match
  290.         CALL    Displ_Changed_Msg         ;Report detection of changed record
  291. Found_matching_NEW_rec:
  292. ;       Now zero out 1st byte of the matched NEW file record:
  293.         XOR     AX,AX                     ;Zeros to store on key of record
  294.         STOSB                             ;Store zero byte at start of record
  295.         POP     DI                        ;point to last current rec on NEW file
  296.         MOV     CX,DX                     ;Restore OLD file recs remaining count
  297.         LOOP    Check_Next_OLD_rec        ;Go check next record on OLD file
  298.         RET                               ;All done with COMPARE_FILE
  299.  
  300.  
  301. ;---------------------------------------------------------------------------;
  302. ; Scan for Additions:                                                       ;
  303. ;   Scan through the NEW file and look for records which have not had the   ;
  304. ;   1st byte zeroed. These recs represent added files. We will put out a     ;
  305. ;   message recording this fact.                                            ;
  306. ; ENTRY:  ES is segment register for NEW file                                ;
  307. ;---------------------------------------------------------------------------;
  308. Scan_for_Additions:
  309.         MOV     AX,CS                     ;Used to access normal DATA segment
  310.         MOV     DS,AX                     ;DS=CS  (normal DATA segment)
  311.         CMP     Changes_only,'Y'          ;Does user want only changes?
  312.         JNE     Scan_continue             ;   If not execute rest of procedure
  313. Scan_early_Exit:
  314.         RET                               ;   Otherwise, pack up and go home
  315. Scan_continue:
  316.         MOV     CX,NEW_Rec_Count          ;Get # of 25 char recs on NEW file
  317.         JCXZ    Scan_Early_Exit           ;If no NEW records to scan
  318.         XOR     DI,DI                     ;1st record on NEW file, displ = 0
  319.         SUB     DI,Rep_rec_len            ;Point to record # -1
  320.         MOV     AX,ES                     ;Use both segment regs for NEW file
  321.         MOV     DS,AX
  322. Check_for_Next_Addition:
  323.         ADD     DI,Rep_rec_len            ;Look at next NEW file record
  324.         CMP     BYTE PTR [DI],0           ;Is this a zeroed record?
  325.         JE      Continue_Zero_Check       ;  If zeroed, keep checking
  326.         CALL    Displ_added_Msg           ;  Else record file addition
  327. Continue_Zero_Check:
  328.         LOOP    Check_For_Next_Addition
  329.         RET
  330.  
  331. ;---------------------------------------------------------------------------;
  332. ; COMPARE TOTALS  - If both OLD and NEW files have total lines check that   ;
  333. ;   they match. If they match, yet files were changed then put out a message;
  334. ;   to that effect and return ERRORLEVEL 4 at termination (BL reg).         ;
  335. ; ENTRY:  ES is segment register for NEW file                               ;
  336. ; EXIT:   DS is back to original Data Segment (=CS)                         ;
  337. ;         BL = 4 if records have changed but both totals match.             ;
  338. ;---------------------------------------------------------------------------;
  339. Compare_totals:                           ;Check if total===> lines match
  340.         MOV     AX,CS                     ;Set DS back to datasegment
  341.         MOV     DS,AX
  342.         MOV     SI,OLD_Tot_Loc            ;Point to location of totals
  343.         CMP     SI,0                      ;Check if totals line non-existant
  344.         JNE     Continue_totals_1         ;  If it exists, chk other totals line
  345.         RET                               ;  ELSE pack up and go home
  346. Continue_totals_1:
  347.         MOV     DI,NEW_Tot_Loc            ;Point to location of totals
  348.         CMP     DI,0                      ;Check if totals line non-existant
  349.         JNE     Continue_totals_2         ;  If it exists, compare the totals
  350.         RET                               ;  ELSE pack up and go home
  351. Continue_totals_2:
  352.         CMP     BH,0FFh                   ;See if page mode is off (= FFh)
  353.         JE      Continue_totals_3         ;   IF turned off, skip page control
  354.         MOV     AL,1                      ;   Else Set lines to be output to 2
  355.         CALL    Page_Control              ;     +  check if its time to pause
  356. Continue_totals_3:
  357.         MOV     AX,ES                     ;NEW file segment
  358.         SUB     AX,File_Size_PARAs        ;Backup segment to point to OLD file
  359.         MOV     DS,AX                     ;DS is OLD file segment register again
  360.         MOV     CX,4                      ;Compare 4 bytes
  361.         REPE    CMPSB                     ;Compare
  362.         MOV     AX,CS                     ;Set DS back to datasegment
  363.         MOV     DS,AX
  364.         MOV     BP,BX                     ;Save highest errorlevel + line ct
  365.         MOV     BX,1                      ;Handle for std output device
  366.         JE      Totals_Match
  367.         MOV     DX, offset Tot_nomatch_Msg
  368.         MOV     CX,21                     ;Length of msg is 21 chars
  369.         MOV     AH,40h                    ;DOS Write func
  370.         INT     21h                       ;Tell user that totals don't match
  371.         MOV     BX,BP                     ;Restore saved BX (ERRLVL + LINEct)
  372.         RET
  373. Totals_match:
  374.         MOV     DX, offset Tot_match_Msg
  375.         MOV     CX,19                     ;Length of msg
  376.         MOV     AH,40h                    ;DOS Write func
  377.         INT     21h                       ;Tell user file totals are equal
  378.         MOV     BX,BP                     ;Restore saved BX (ERRLVL + LINEct)
  379.         OR      BL,BL                     ;Check if any file chgs,dels or adds
  380.                                           ;           (IE, BL not = 0)
  381.         JE      Totals_Return             ;   If no changes then we are done...
  382.         MOV     BL,4                      ;   ELSE, indicate probable rename
  383. Totals_Return:
  384.         RET
  385.  
  386. ;---------------------------------------------------------------------------;
  387. ; Display CHANGED Message                                                   ;
  388. ;                                                                           ;
  389. ;ENTRY: DS:SI points to OLD version of report record to format + display.   ;
  390. ;       ES:DI points to NEW version of report record to format + display.   ;
  391. ;EXIT:                                                                      ;
  392. ;   Prints a message to standard output device informing user that a change ;
  393. ;   has occured between the OLD and NEW files. IF /P was selected then      ;
  394. ;   we check line count and pause every 24 lines.                           ;
  395. ;---------------------------------------------------------------------------;
  396. Displ_Changed_Msg:                    ;Display msg announcing changed records
  397.         PUSH    BP
  398.         PUSH    CX
  399.         PUSH    DX
  400.         PUSH    DS                        ;Save (OLD) file segment
  401.         MOV     AX,CS                     ;Used to access normal DATA segment
  402.         MOV     DS,AX                     ;DS=CS  (normal DATA segment)
  403.         OR      BL,BL                     ;Check if highest error level (BL) = 0
  404.         JNZ     Check_CHG_Page_mode       ;  If not 0, then header msg alrdy out
  405.         CALL    Print_Header_Msg          ;  Else Display the header message
  406. Check_CHG_Page_mode:
  407.         CMP     BH,0FFh                   ;See if page mode is off (= FFh)
  408.         JE      Print_changed_cont        ;   IF turned off, skip page control
  409.         MOV     AL,2                      ;   Else Set lines to be output to 2
  410.         CALL    Page_Control              ;     +  check if its time to pause
  411. Print_changed_cont:
  412.         MOV     BP,BX                     ;Save BX in BP
  413.         MOV     DX, offset CHGD_Msg_1     ;First part of changed messaged
  414.         MOV     CX,10                     ;Length of msg is 10 chars
  415.         MOV     AH,40h                    ;DOS Write func
  416.         MOV     BX,1                      ;BX=1 = Handle for std output device
  417.         INT     21h                       ;Write beginning of OLD file chngd msg
  418.         POP     DS                        ;Use file segment again (OLD file)
  419.         SUB     SP,2                      ;Leave DS on stack
  420.         MOV     DX,SI                     ;Point to OLD record
  421.         Call    Format_and_Display_Rec    ;Format compressed record for display
  422.         MOV     AX,CS                     ;Used to access normal DATA segment
  423.         MOV     DS,AX                     ;Back to normal data segment again
  424.         MOV     DX, offset CHGD_Msg_2     ;First part of changed messaged
  425.         MOV     CX,10                     ;Length of msg is 10 chars
  426.         MOV     AH,40h                    ;DOS Write func
  427.         INT     21h                       ;Write beginning of OLD file chngd msg
  428.         MOV     AX,ES                     ;Use file segment again (NEW file)
  429.         MOV     DS,AX
  430.         MOV     DX,DI                     ;Point to NEW record
  431.         Call    Format_and_Display_Rec    ;Format compressed record for display
  432.         MOV     BX,BP                     ;Restore Saved version of BX
  433.         POP     DS                        ;Restore addressability to OLD file
  434.         POP     DX
  435.         POP     CX
  436.         POP     BP
  437.         MOV     BL,12                     ;Indicate a record has changed
  438.         RET
  439.  
  440. ;---------------------------------------------------------------------------;
  441. ; Display DELETED Message                                                   ;
  442. ;                                                                           ;
  443. ;ENTRY: DS:SI points to OLD version of report record to format + display    ;
  444. ;       which was deleted between the OLD and the NEW report files.         ;
  445. ;EXIT:                                                                      ;
  446. ;   Prints a message to standard output device informing user that a file   ;
  447. ;   has been deleted from the OLD file list.   IF /P was selected then      ;
  448. ;   we check line count and pause every 24 lines.                           ;
  449. ;---------------------------------------------------------------------------;
  450. Displ_Deleted_Msg:                    ;Display msg announcing deleted
  451.         PUSH    BP
  452.         PUSH    CX                        ;Save used registers
  453.         PUSH    DX
  454.         PUSH    DS                        ;Save (OLD) file segment
  455.         MOV     AX,CS                     ;Used to access normal DATA segment
  456.         MOV     DS,AX                     ;DS=CS  (normal DATA segment)
  457.         CMP     Changes_only,'Y'          ;Does user want only changes?
  458.         JNE     Displ_Deleted_continue    ;   If not continue
  459.         POP     DS                        ;   ELSE restore DS and return
  460.         JMP     Displ_Deleted_Exit2       ;                           to caller
  461. Displ_Deleted_continue:
  462.         OR      BL,BL                     ;Check if highest error level (BL) = 0
  463.         JNZ     Check_DEL_Page_mode       ;  If not 0, then header msg alrdy out
  464.         CALL    Print_Header_Msg          ;  Else Display the header message
  465. Check_DEL_Page_mode:
  466.         CMP     BH,0FFh                   ;See if page mode is off (= FFh)
  467.         JE      Displ_Deleted_continue2   ;   IF turned off, skip page control
  468.         MOV     AL,1                      ;   Else Set lines to be output to 2
  469.         CALL    Page_Control              ;     +  check if its time to pause
  470. Displ_Deleted_continue2:
  471.         MOV     BP,BX                     ;Save BX
  472.         MOV     DX, offset DELETED_Msg    ;First part of deleted message
  473.         MOV     CX,10                     ;Length of msg is 10 chars
  474.         MOV     AH,40h                    ;DOS Write func
  475.         MOV     BX,1                      ;Handle for std output device
  476.         INT     21h                       ;Write beginning of OLD file dltd msg
  477.         POP     DS                        ;Use file segment again (OLD file)
  478.         MOV     DX,SI                     ;Point to OLD record
  479.         Call    Format_and_Display_Rec    ;Format compressed record for display
  480. Displ_Deleted_Exit:
  481.         MOV     BX,BP                     ;Restore saved version of BX
  482.         CMP     BL,8                      ;Check if Delete or chg already hapnd
  483.         JAE     Displ_Deleted_Exit2       ;   Do not change if already set
  484.         MOV     BL,8                      ;Flag that Deleted record detected
  485. Displ_Deleted_Exit2:
  486.         POP     DX
  487.         POP     CX
  488.         POP     BP
  489.         RET
  490.  
  491.  
  492. ;---------------------------------------------------------------------------;
  493. ;Display ADDED Message  -Indicate that a file has been added since OLD reprt;
  494. ;                                                                           ;
  495. ;ENTRY: ES:DI points to NEW version of report record to format + display.   ;
  496. ;EXIT:                                                                      ;
  497. ;   Prints a message to standard output device informing user that a file   ;
  498. ;   has been added to the NEW file list.   IF /P was selected then          ;
  499. ;   we check line count and pause every 24 lines.                           ;
  500. ;---------------------------------------------------------------------------;
  501. Displ_added_Msg:                      ;Print message announcing additional files
  502.         PUSH    BP
  503.         PUSH    CX                        ;Save used registers
  504.         MOV     AX,CS                     ;Used to access normal DATA segment
  505.         MOV     DS,AX                     ;DS=CS  (normal DATA segment)
  506.         OR      BL,BL                     ;Check if highest error level (BL) = 0
  507.         JNZ     Check_ADD_Page_mode       ;  If not 0, then header msg alrdy out
  508.         CALL    Print_Header_Msg          ;  Else Display the header message
  509. Check_ADD_Page_mode:
  510.         CMP     BH,0FFh                   ;See if page mode is off (= FFh)
  511.         JE      Displ_Added_continue      ;   IF turned off, skip page control
  512.         MOV     AL,1                      ;   Else Set lines to be output to 2
  513.         CALL    Page_Control              ;     +  check if its time to pause
  514. Displ_added_continue:
  515.         MOV     BP,BX                     ;Save BX
  516.         MOV     DX, offset Added_Msg      ;First part of deleted message
  517.         MOV     CX,10                     ;Length of msg is 10 chars
  518.         MOV     AH,40h                    ;DOS Write func
  519.         MOV     BX,1                      ;Handle for std output device
  520.         INT     21h                       ;Write beginning of file added msg
  521.         MOV     AX,ES                     ;Use file segment again (NEW file)
  522.         MOV     DS,AX                     ;DS=ES (both are seg reg for NEW file)
  523.         MOV     DX,DI                     ;Point to rec on NEW file (Added rec)
  524.         Call    Format_and_Display_Rec    ;Format compressed record for display
  525.         MOV     BX,BP                     ;Restore saved version of BX
  526.         POP     CX
  527.         POP     BP
  528.         CMP     BL,8                      ;Chk if Del, add or chg already hapnd
  529.         JAE     AD_or_CHG_happened        ;   Do not change if already set
  530.         MOV     BL,8                      ;Flag that Deleted record detected
  531. AD_or_CHG_happened:
  532.         RET
  533.  
  534. ;---------------------------------------------------------------------------;
  535. ; Allocate Memory                                                           ;
  536. ;                                                                           ;
  537. ; ENTRY: BX contains starting offset of buffer area.                        ;
  538. ;        (Note, this area contains initialization code and data which will  ;
  539. ;        be overlaid once we start reading into the buffers.)               ;
  540. ;                                                                           ;
  541. ;   Release memory used by initialization routine and allocate 2000h pages  ;
  542. ;   (128K) as file buffers, failing that get as much memory as possible.    ;
  543. ;   Leaves ES as segment pointer to first  file segment (OLD file).         ;
  544. ;---------------------------------------------------------------------------;
  545. Allocate_Memory:
  546.  
  547. ; Now determine how many paragraphs (16 bytes) program plus stack needs:
  548.         ADD     BX,15                     ;Round up to nearest PARA
  549.         MOV     CL,4
  550.         SHR     BX,CL                     ;Divide bytes of storage by 16
  551.  
  552.         MOV     AH,4Ah                    ;Dealloc all but needed (BX) paras
  553.         INT     21h
  554.  
  555.         MOV     BX,2000h                  ;Request 128K for input buffers
  556.         MOV     AH,48h                    ;DOS request mem function
  557.         INT     21h
  558.         JNC     Mem_OK                    ;If memory is available
  559.  
  560.         MOV     DX,offset Mem_loss_Msg    ;Display msg informing lack of mem
  561.         MOV     AH,09h                    ;DOS display string function
  562.         INT     21h
  563. ; Attempt to allocate what little memory is available and use that
  564.         MOV     AX,BX                     ;Paragraphs of memory free
  565.         SHR     AX,1                      ;Divide by two: Space for each file
  566.         MOV     File_Size_PARAs,AX        ;Each file's size in pargraphs
  567.         MOV     CL,4                      ;Prepare to shift left 4 bits (*16)
  568.         SHL     AX,CL                     ;Mult by 16 = number of bytes per file
  569.         MOV     File_Size_Bytes,AX        ;Space for each file in bytes
  570.         MOV     AH,48h                    ;DOS alloc mem func:BX = para avail
  571.         INT     21h                       ;Get what memory we can get
  572.         JNC     Mem_OK                    ;If Alloc worked 2nd time around
  573.  
  574. ; Fatal memory error:
  575.         MOV     DX,offset Mem_ERR_Msg     ;Else: give message and give up
  576.         MOV     AH,09h                    ;DOS display string function
  577.         INT     21h
  578.         CALL    Page_Wait                 ;Beep and force user to hit a key
  579.         MOV     AX,4C14h                  ;   terminate with 20 error level
  580.         INT     21h
  581.  
  582. Mem_OK:
  583.         MOV     ES,AX                     ;ES points to start of allcoated block
  584.         RET
  585.  
  586. ;---------------------------------------------------------------------------;
  587. ; Read and Validate Files                                                   ;
  588. ;   1) Read both files into file buffers.                                   ;
  589. ;   2) Validate that files are of correct type and uncorrupted:int chk data ;
  590. ;   3) Determine offset of first record and total number of records         ;
  591. ;      check if a total line exists on each file                            ;
  592. ;   4) Calc offset of beginning of last record for the NEW file             ;
  593. ;                                                                           ;
  594. ; On Entry ES must point to OLD_FILE segment                                ;
  595. ;                                                                           ;
  596. ; On Exit  ES will point to NEW_FILE segment and DS will be DATA SEG (=CS)  ;
  597. ;---------------------------------------------------------------------------;
  598. Read_and_Validate_Files:
  599.  
  600. ;  Read "OLD" file (first of two files specified)
  601.         MOV     BX,OLD_File_Handle        ;Get handle for the first file
  602.         PUSH    OLD_Filename_end          ;Save end of Filename on stack
  603.         PUSH    OLD_Filename_Loc          ;Save start of filename for error msgs
  604.         MOV     AX,ES                     ;ES points to beginning of file SEG
  605.         MOV     DS,AX                     ;DS=ES = seg reg for OLD file
  606.         CALL    Read_File                 ;Do actual read of file + error chking
  607.         CALL    Validate_File             ;Check file and locate 1st + last recs
  608.                                           ;DS = CS after return from Validate_Fi
  609.         ADD     SP,4                      ;Remove filename end + loc from stack
  610.         MOV     OLD_Rec_count,CX          ;Save number of records
  611.         MOV     OLD_Tot_Loc,DI            ;Save location of totals
  612.  
  613. ;  Read "NEW" file (2nd of two files specified)
  614.         MOV     BX,NEW_File_Handle        ;Get handle for the first file
  615.         PUSH    NEW_Filename_end          ;Save end of Filename on stack
  616.         PUSH    NEW_Filename_Loc          ;Save start of filename for error msgs
  617.         MOV     AX,ES                     ;DS points to beginning of file SEG
  618.         ADD     AX,File_Size_PARAs        ;point DS to NEW file segment
  619.         MOV     DS,AX                     ;DS is segment register for NEW file
  620.         CALL    Read_File                 ;Do actual read of file + error chking
  621.         MOV     AX,DS                     ;Validate_file needs
  622.         MOV     ES,AX                     ;                    ES for file seg
  623.         CALL    Validate_File             ;Check file and locate 1st + last recs
  624.                                           ;DS = CS after return from Validate_Fi
  625.         ADD     SP,4                      ;Remove filename end + loc from stack
  626.         MOV     NEW_Rec_count,CX          ;Save number of records
  627.         MOV     NEW_Tot_Loc,DI            ;Save location of totals (if existing)
  628.         MOV     NEW_End_Of_File,DI        ;Save Offset past last 25 chr rec
  629.         RET
  630.  
  631. ;---------------------------------------------------------------------------;
  632. ; READ FILE - will read the file specified by the following parameters      ;
  633. ;   BX contains file handle, Stack contains end and start of filespec       ;
  634. ;   DS contains segment to read file into (file buffer is at offset zero)   ;
  635. ; On EXIT:  File will be read into file buffer and closed.                  ;
  636. ;           CX will contain number of characters read in from the file.     ;
  637. ;---------------------------------------------------------------------------;
  638. Read_file:
  639.         CMP     CS:Missing_Old_File,'Y'   ;Are we attempting to read from a
  640.                                           ; Non-existant OLD file?
  641.         JNE     Normal_File_Read          ;   If not, do normal file read
  642.         XOR     CX,CX                     ;   Else, indicate file is empty
  643.         MOV     CS:Missing_Old_File,0     ;   Turn off missing file switch
  644.         RET                               ;   All done for missing file
  645.  
  646. Normal_File_Read:
  647.         XOR     DX,DX                     ;DX=0 = start of  file buffer
  648.         MOV     SI,DX                     ;SI is for BUFFER reads later
  649.         MOV     CX,CS:File_Size_Bytes     ;MAX # of bytes to read (Nrmly:64k-1)
  650.         MOV     AH,3Fh                    ;Setup to read from file
  651.         INT     21h                       ;Call DOS to do actual read
  652.         JC      Read_error                ;Quit on any error or EOF
  653.         CMP     AX,CX                     ;See if max number of characters read
  654.         JE      File_size_error           ;If we have compltly filled buffer
  655.         MOV     CX,AX                     ;Save total # of chars read
  656.         MOV     AH,3Eh                    ;Prepare to close the file
  657.         INT     21h                       ;Let DOS close file
  658.         RET
  659.  
  660. ;---------------------------------------------------------------------------;
  661. ; READ ERROR - report read error message - call with:                       ;
  662. ;   DI = offset to end of filename, BP= start of filename with read error   ;
  663. ;---------------------------------------------------------------------------;
  664. Read_error:                               ;Report error reading a file
  665.         MOV     AX,CS
  666.         MOV     DS,AX                     ;Restore datasegment addressability
  667.         MOV     DX, offset Read_Err_Msg   ;indicate read failed
  668.         MOV     CX,15                     ;Length of msg is 15 chars
  669.         MOV     SI,4C14h                  ;DOS term with error level 20
  670.         JMP     Report_file_errors
  671.         SUBTTL  General Purpose subroutines
  672.  
  673. ;---------------------------------------------------------------------------;
  674. ; FILE SIZE ERROR - Report on an error - with file have too many records    ;
  675. ;   Stack contains end and start of filespec with error                     ;
  676. ;---------------------------------------------------------------------------;
  677. File_size_error:                          ;File has too many records for mem
  678.         MOV     AX,CS
  679.         MOV     DS,AX                     ;Restore datasegment addressability
  680.         MOV     DX, offset size_Err_Msg   ;indicate file size too large
  681.         MOV     CX,21                     ;Length of msg is 21 chars
  682.         MOV     SI,4C10h                  ;DOS term with error level 16 (dec)
  683.         JMP     Report_file_errors
  684.  
  685. ;---------------------------------------------------------------------------;
  686. ; FILE TYPE ERROR - Report on an error - with file being invalid type       ;
  687. ;   Stack contains the END and (LOC) start of the filespec for error msgs   ;
  688. ;---------------------------------------------------------------------------;
  689. File_type_error:                          ;Report this is wrong type of file
  690.         MOV     AX,CS
  691.         MOV     DS,AX                     ;Restore datasegment addressability
  692.         MOV     DX, offset type_Err_Msg   ;indicate bad file type
  693.         MOV     CX,20                     ;Length of msg is 20 chars
  694.         MOV     SI,4C10h                  ;DOS term with error level 16 (dec)
  695.         JMP     Report_file_errors
  696.  
  697. ;---------------------------------------------------------------------------;
  698. ; VALIDATE FILE - will examine file and locate 1st and last records in file.;
  699. ;     Will also detect file corruption, by computing TOT_Rec check data and ;
  700. ;     comparing with that stored in TOT_REC check data fields.              ;
  701. ; On Entry:                                                                 ;
  702. ;   Stack contains the END and (LOC) start of the filespec for error msgs   ;
  703. ;   ES contains File buffer SEGMENT                                         ;
  704. ;   CX contains number of characters read in the buffer                     ;
  705. ; On EXIT: (if file is of valid type:)                                      ;
  706. ;   CX will be count of number of records on file                           ;
  707. ;   DI will be = offset of CHKSUM field on final totals record              ;
  708. ;      this is the same as the offset of last char in last 25 char record +1;
  709. ;   DS will be code/data segment register rather than File segment          ;
  710. ;   AX,BX,BP,DX will all be corrupted (are not saved and restored).         ;
  711. ;---------------------------------------------------------------------------;
  712. Validate_File:
  713.         MOV     AX,CS                     ;XFER OLD data SEG(=CS)
  714.         MOV     DS,AX                     ;                        back into DS
  715.         XOR     BP,BP                     ;Start at beginning of buffer
  716.  
  717. ;Handle case were file is non existant or is a 1 byte zero record file
  718.         CMP     CX,REP_Rec_Len           ;Do we have at least one record?
  719.         JAE     File_has_Records         ;  Yes, do normal validation of file
  720.         CMP     CX,1                     ;Do we have more than 1 char on file?
  721.         JA      File_Type_Error          ;  If so this is an invalid file
  722.         XOR     CX,CX                    ;  Else indicate this a null file
  723.  
  724. File_has_Records:
  725. ; BP now points to the first 25 char record on this file
  726.         MOV     DI,CX                     ;Save a copy of # of chars on file
  727. ; Now check for existance of TOTALS record and locate beginning of last rec
  728.         XOR     DX,DX                     ;Zero upper part of dividend (DX:AX)
  729.         MOV     AX,CX                     ;# of chars after start of 1st record
  730.         MOV     BX,Rep_rec_len            ;Prepare to divide by record len (25)
  731.         DIV     BX                        ;Divide chars from 1st rec by 25
  732. ;       After divide: # of 25 char recs is in AX; # of chars in last rec in DX
  733.         MOV     CX,AX                     ;# of 25 character records on file
  734.         XOR     BX,BX                     ;  Initially indicate no totals line
  735.         JCXZ    Return_from_Validate      ;If no records on file, we are done..
  736.         CMP     DX,Tot_Rec_Len            ;Length of totals/chk line should = DX
  737.         JE      Chk_File_Type_Byte        ;   If length is correct for tot line
  738.         JMP     File_type_error           ;   If length of final line is wrong
  739. Chk_File_Type_Byte:
  740.         CMP     ES:[BP.Rep_F_Type],5      ;   IF not check 1st file type byte
  741.         JB      FT_is_OK                  ;      If 0, 1, 2, 3, or 4, its OK
  742.         JMP     File_type_error           ;      otherwise file is corrupted
  743. FT_is_OK:
  744. ;               DI contains char count (EOF byte offset +1)
  745.         SUB     DI,Tot_Rec_Len            ;first char in CHKSUM field of TOT rec
  746.         CALL    Detect_File_Corruption    ;Verify file is OK by re-computing
  747.                                           ;  Tot_Rec check values and comparing
  748. Return_from_validate:
  749.         RET
  750.  
  751. ;-----------------------------------------------------------------------------;
  752. ;  DETERMINE THAT THE REPORT FILE ITSELF HAS NOT BEEN CORRUPTED:              ;
  753. ;-----------------------------------------------------------------------------;
  754. ;  Calculate CHK + XOR values for the file itself and compare results with the;
  755. ;  data in the last 2 bytes of the file (The 4 byte TOT_Rec).                 ;
  756. ;                                                                             ;
  757. ;  ENTRY: DI  points to start of totals record (the chksum field)             ;
  758. ;  EXIT:  Jumps to File_Type_Error if corruption is detected.                 ;
  759. ;                                                                             ;
  760. ;  AX,BX,DX,SI  are all corrupted. (not saved and restored)                   ;
  761. ;-----------------------------------------------------------------------------;
  762. Detect_File_Corruption:
  763.         PUSH    CX                        ;Save critical registers
  764.         PUSH    DS
  765.         MOV     AX,ES                     ;Set DS back to file buffer
  766.         MOV     DS,AX
  767.         XOR     SI,SI                     ;Start of File buffer (offset=0)
  768.         MOV     CX,DI                     ;OFFSET TOT_REC = # of chars bfor tot
  769.         CALL    Calc_Sums                 ;Compute check data for report file
  770.         CMP     DX,WORD PTR [DI.Tot_Int_XOR] ;Compare computed + stored CHK val
  771.         JE      Check_XOR                 ;  IF CHK values match, check XOR val
  772.         ADD     SP,6                      ;   Remove return adr from stackand
  773.         JMP     File_Type_Error           ;      report file as a bad file
  774. Check_XOR:
  775.         CMP     BX,WORD PTR [DI.Tot_Int_CHK] ;Compare computed + stored XOR val
  776.         JE      CHK_Done                  ;  IF XOR values match, all is OK
  777.         ADD     SP,2                      ;   Remove return adr from stackand
  778.         JMP     File_Type_Error           ;      report file as a bad file
  779. CHK_Done:
  780.         POP     DS                        ;Restore critical registers
  781.         POP     CX
  782.         RET
  783.  
  784.         SUBTTL  General Purpose Subroutines
  785. ;******************************************************************************;
  786. ;**   General purpose subroutines follow                                     **;
  787. ;******************************************************************************;
  788.  
  789. ;---------------------------------------------------;
  790. ; C A L C _  S U M S -  Calculate check values      ;
  791. ;---------------------------------------------------;
  792. ; This is a special version for CFCOMPC + CHKfileC. ;
  793. ;---------------------------------------------------;
  794. ; INPUT:  SI = pointer to file BUFFER to scan       ;
  795. ;         CX = # of characters to read              ;
  796. ;                                                   ;
  797. ;Register conventions:                              ;
  798. ;                                                   ;
  799. ; AL - Each new character read into this register   ;
  800. ; CX - number of chars read in -decreasing counter  ;
  801. ; BX - Contains check value 1 (checksum)            ;
  802. ; DX - XOR check value 2 (XOR) for this file        ;
  803. ; SI - index pointing into file BUFFER              ;
  804. ;                                                   ;
  805. ;  None of the above registers are saved/restored.  ;
  806. ; --------------------------------------------------;
  807. Calc_Sums:
  808.         XOR     DX,DX                     ;Zero check value 2 (XOR hash)
  809.         XOR     BX,BX                     ;Zero check value 1 (SUM)
  810.         XOR     AH,AH                     ;Zero upper part of AX for addition
  811.  
  812. ; Innermost  char loop  - keep this fast!
  813. NEXT_CHAR:
  814.         LODSB                             ;Get char into AL
  815.         ROR     DX,1                      ;Keep shifting to XOR to right
  816.         XOR     DL,AL                     ;cumulative XOR into DX
  817.         SUB     BX,AX                     ;cumulative check subtraction
  818.         LOOP    NEXT_CHAR                 ;CONTINUE SCANNING CHARS UNTIL EOB
  819.         RET                               ;All done calculating sums!
  820.  
  821. ;---------------------------------------------------------------------------;
  822. ;Format and Display Record - Formats and displays compressed report records.;
  823. ;   The compressed fields in the report records with be expanded/decrypted  ;
  824. ;   and formatted for display and then written to the standard output device;
  825. ;                                                                           ;
  826. ;Entry: DS:DX must point to the 25 character report record to be displayed. ;
  827. ;                                                                           ;
  828. ;Exit: Formatted form of report record will be displayed on STD output.     ;
  829. ;---------------------------------------------------------------------------;
  830. Format_and_Display_Rec:
  831.         PUSH    BP
  832.         PUSH    BX
  833.         PUSH    DI
  834.         PUSH    DS
  835.         PUSH    ES
  836.         PUSH    SI
  837.         MOV     AX,CS                     ;Used to access normal DATA segment
  838.         MOV     ES,AX                     ;ES allows us to addr in data segment
  839.         ASSUME  DS:Nothing, ES:CSEG       ;Tell ASM to use ES to addr norm data
  840.  
  841. ;-----------------;
  842. ; Format file name;
  843.         MOV     CX,12                     ;Scan 12 characters of filename
  844.         MOV     DI,OFFSET DSP_Rec         ;Start of DSP_REC - file for display
  845.         MOV     SI,DX                     ;Start of Rep_Rec (compressed report)
  846.         MOV     BP,DX                     ;Save the start of the record
  847.         INC     SI                        ;Skip to start of filename field
  848.  
  849. Xfer_file_name:                           ;Xfer filename from Rep_Rec to DSP_REC
  850.         LODSB                             ;Load 1 byte from Rep_Rec for transfr
  851.         OR      AL,AL                     ;See if this=0 (end of file name)
  852.         JZ      Blank_fill                ;If end, then blank fill rest of name
  853.         ROR     AL,1                      ;Decrypt the filename
  854.         STOSB                             ;Else store char in OutRec file name
  855.         LOOP    Xfer_file_name            ;continue until done
  856.         JMP     Short Check_File_Type     ;Go and format file size for output
  857.  
  858. Blank_fill:                               ;blank fill remainder of file name out
  859.         MOV     AL,' '
  860.         REP     STOSB                     ;Store remaining characters
  861.  
  862. Check_File_Type:                          ;What file type is this?
  863.         MOV     AL,BYTE PTR DS:[BP]       ;Pick up the file type byte
  864.  
  865.         CMP     AL,1                      ;Is this a normal file (=1) ?
  866.         JE      Cnvt_CHKvals              ;  Its a file, so do normal processing
  867.         CMP     AL,2                      ;Is this a directory entry  ?
  868.         JE      Process_directory         ;  Its a directory
  869.         CMP     AL,3                      ;Is it a file with open error?
  870.         JE      Process_File_with_OPNerr  ;  Its a file CHKfileC couldn't open
  871.         CMP     AL,4                      ;Is it a file that had an I/O error?
  872.         JE      Process_File_with_IOerr   ;  Its a file CHKfileC couldn't read
  873.  
  874.  
  875.  
  876. Process_directory:
  877. ; Do special handling for directory entries (rather than file entries):
  878.         MOV     DI,offset DSP_CHK_Sum     ;prep to place msg in chk sum field
  879.         MOV     AX,'iD'                   ;Store "Dir." in display record
  880.         STOSW                             ;  to indicate this is a directory
  881.         MOV     AX,'.r'                   ;  entry rather than a normal file.
  882.         STOSW
  883.         MOV     CX,5                      ;Now blank fill the remainder of
  884.         MOV     AL,' '                    ;    the report record chk value 2
  885.         REP     STOSB
  886.         JMP     SHORT Format_F_Size       ;Do not format check values (1+2)
  887.  
  888. Process_file_with_OPNerr:                 ;This is a file CHKfileC couldn't open
  889.         MOV     SI,OFFSET File_Open_Err_Msg    ;Data to replace check values
  890.  
  891. Process_bad_files:                        ;Come here to displ MSGs (adr in SI)
  892.         PUSH    DS                        ;Save DS (adr into file segment)
  893.         MOV     AX,CS
  894.         MOV     DS,AX                     ;DS must adr data segment for MOVSB
  895.         MOV     DI,OFFSET DSP_CHK_Sum     ;Field to indicate
  896.         MOV     CX,9                      ;Message has 9 chars
  897.         REP     MOVSB
  898.         POP     DS                        ;Restore addressing to file segment
  899.         JMP     SHORT Format_F_Size       ;Go display rest of file info
  900.  
  901. Process_file_with_IOerr:                  ;This is a file CHKfileC couldn't read
  902.         MOV     SI,OFFSET File_Read_Err_Msg ;File IO error msg to put in DSP rec
  903.         JMP     SHORT Process_Bad_Files   ;Go put message in DSP_REC
  904.  
  905. Cnvt_CHKvals:                             ;Convert Check values for display
  906.         MOV     SI,BP                     ;Point back to the start of the rec
  907.         MOV     BX,[SI.REP_CHK_SUM]       ;Get CHKsum (check val 1) in BX
  908.         MOV     CX,[SI.REP_XOR_SUM]       ;GET XORsum (check val 2) in CX
  909.         CALL    Convert_Sums_for_Display  ;Convert to display form and place in
  910.                                           ;  the the display record (DSP_REC)
  911. ; --------------------------------------------------;
  912. ; Extract file size from Rep_Rec for display        ;
  913. ; --------------------------------------------------;
  914. Format_F_size:                            ;Format Rep_Rec's file size for output
  915.         MOV     DI,offset DSP_F_Size      ;Display formatted file size
  916.         LEA     SI,[BP+Rep_FS_HIr+1]      ;End of Rep_Rec file size area
  917.         MOV     CX,4                      ;process 4 bytes (2 words) file size
  918.         XOR     DX,DX                     ;DX=0 means only leading zeros so far
  919.  
  920. Get_byte_to_Hex_Convert:                  ;Conv each byte to 2 HEX ASCII digits
  921.         MOV     AH,BYTE PTR [SI]          ;Pick up last chr from  Rep_Rec F size
  922.         CALL    Convert_Hex_ASCII         ;Convert 4 bit hex to ASCII displcode
  923.         DEC     SI                        ;Get prior byte in Rep_Rec file size
  924.         LOOP    Get_Byte_to_Hex_Convert   ;Do all four bytes
  925.  
  926. ; --------------------------------------------------;
  927. ; Extract file date from Rep_Rec for display        ;
  928. ; --------------------------------------------------;
  929.         MOV     AX,DS:[BP.Rep_F_date]     ;Date of last file update
  930. ;       date is in yyyyyyym mmmddddd format (year is offset from 1980)
  931.         MOV     DX,AX                     ;Save a copy of file date
  932.         MOV     BL,10                     ;Put 10 in BL for decimal conversion
  933. ;MONTH
  934.         MOV     CL,5                      ;Prepare to shift right 5 bits
  935.         ROR     AX,CL                     ;Move month to right of word
  936.         AND     AX,0Fh                    ;only month remains
  937.         MOV     DI,offset DSP_F_MM        ;Point to month field in DSP_rec
  938.         Call    Convert_Dec_ASCII         ;Convert 2 decimal digits to ASCII
  939.  
  940. ;DAY
  941.         MOV     AX,DX                     ;Restore copy of Rep_Rec date
  942.         AND     AX,1fh                    ;Extract day portion of date
  943.         MOV     DI,OFFSET DSP_F_DD        ;Point to day field in DSP rec
  944.         Call    Convert_Dec_ASCII         ;Convert 2 decimal digits to ASCII
  945.  
  946. ;YEAR
  947.         MOV     AX,DX                     ;Restore copy of Rep_Rec date
  948.         MOV     CL,7
  949.         ROL     AX,CL                     ;Bring year of date to right of AX
  950.         AND     AX,7Fh                    ;MASK off right 7 bits of YEAR
  951.         ADD     AX,80                     ;Year is years after 1980
  952.         CMP     AX,100                    ;Are we in the next century?
  953.         JB      Transfer_year             ;IF not go ahead and display YY
  954.         SUB     AX,100                    ;Otherwise adjust the year
  955. Transfer_year:
  956.         MOV     DI,OFFSET DSP_F_YY        ;Point to year field in DSP_REC
  957.         Call    Convert_Dec_ASCII         ;Convert 2 decimal digits to ASCII
  958.  
  959.  
  960. ; --------------------------------------------------;
  961. ; Extract file time from Rep_Rec for display        ;
  962. ; --------------------------------------------------;
  963.         MOV     AX,DS:[BP.Rep_F_time]     ;time of last file update
  964. ;       time is in hhhhhmmm mmmsssss format (seconds are 0-29 in 2 sec intervl)
  965.  
  966. ;HOURS
  967.         MOV     DX,AX                     ;Create a copy of the time
  968.         MOV     CL,5                      ;Shift for hour bits
  969.         ROL     AX,CL                     ;hours are on the right of AX
  970.         AND     AX,1Fh                    ;Only hours remain in AX
  971.         MOV     DI,OFFSET DSP_F_HH        ;Point so we can mov to hour field
  972.         Call    Convert_Dec_ASCII         ;Convert 2 decimal digits to ASCII
  973.  
  974. ;Minutes
  975.         MOV     AX,DX                     ;Restore copy of the time
  976.         MOV     CL,5
  977.         ROR     AX,CL                     ;Minutes are rightmost in AX
  978.         AND     AX,3Fh                    ;Mask off minutes
  979.         MOV     DI,OFFSET DSP_F_MI        ;Point to minutes in display field
  980.         Call    Convert_Dec_ASCII         ;Convert 2 decimal digits to ASCII
  981.  
  982. ;Seconds
  983.         MOV     AX,DX                     ;Restore copy of the time
  984.         AND     AX,1Fh                    ;Only seconds remain after MASKing
  985.         ROL     AX,1                      ;Multiply secs by 2
  986.         MOV     DI,OFFSET DSP_F_SS        ;Point so we can mov to hour field
  987.         Call    Convert_Dec_ASCII         ;Convert 2 decimal digits to ASCII
  988.         ASSUME  DS:CSEG, ES:Nothing       ;Return ASM to using DS for norm data
  989.  
  990. ; Do actual display of DISPLAY (DSP_REC) record:
  991.         MOV     AX,CS                     ;Used to access normal DATA segment
  992.         MOV     DS,AX                     ;DS allows DOS to access to DSP_REC
  993.         MOV     BX,1                      ;File handle for STD output
  994.         MOV     DX, OFFSET DSP_Rec        ;Location of record to display
  995.         MOV     CX,DSP_Rec_len            ;Length of msg is 51 chars
  996.         MOV     AH,40h                    ;DOS Write func
  997.         INT     21h                       ;Write actual OLD report rec out
  998.         POP     SI
  999.         POP     ES
  1000.         POP     DS
  1001.         POP     DI
  1002.         POP     BX
  1003.         POP     BP
  1004.         RET
  1005.  
  1006. ;------------------------------------------------------------------------------;
  1007. ; Convert 16 bit check values to ASCII hex characters and store in DSP_Rec     ;
  1008. ;------------------------------------------------------------------------------;
  1009. ;Input: BX contains checksum (16 bit) (Check value # 1)                        ;
  1010. ;       CX contains 16 exclusive or sum (XOR, Check value # 2)                 ;
  1011. ;Output: DSP_Rec will contain display versions of chk and XOR sums             ;
  1012. ;        AX,DX and DI will be corrupted.                                       ;
  1013. ;------------------------------------------------------------------------------;
  1014. Convert_Sums_for_Display:                 ;Come here only for files not DIRs
  1015.                                           ; chksum (val1) in BX, XOR(val2) in CX
  1016.         MOV     DI,OFFSET DSP_CHK_Sum     ;Field for hex ASCII characters
  1017.         MOV     AH,BH                     ;Upper byte of checksum (chk value 1)
  1018.         MOV     DL,01                     ;DX<>0 turns off leading 0 suppression
  1019.         CALL    Convert_Hex_ASCII         ;Convert to 2 hex ASCII characters
  1020.         MOV     AH,BL                     ;Lower byte of checksum (chk val 1)
  1021.         CALL    Convert_Hex_ASCII         ;Convert to 2 hex ASCII characters
  1022.         INC     DI                        ;Skip over space + into XOR field
  1023.         MOV     AH,CH                     ;Upper byte of XOR (chk value 2)
  1024.         CALL    Convert_Hex_ASCII         ;Convert to 2 hex ASCII characters
  1025.         MOV     AH,CL                     ;lower byte of XOR (chk value 2)
  1026.         CALL    Convert_Hex_ASCII         ;Convert to 2 hex ASCII characters
  1027.         RET
  1028.  
  1029. ;------------------------------------------------------------------------------;
  1030. ;   CONVERT HEX ASCII   -  Convert hex byte (8 bits) to 2 ASCII display bytes  ;
  1031. ;------------------------------------------------------------------------------;
  1032. Convert_Hex_ASCII:
  1033.       CALL      Convert_Hex_Nyble_ASCII   ;Convert nyble (4 bits) to hex ASCII
  1034.       CALL      Convert_Hex_Nyble_ASCII   ;Convert nyble (4 bits) to hex ASCII
  1035.       RET                                 ;RETURN to caller
  1036.  
  1037. ;------------------------------------------------------------------------------;
  1038. ; CONVERT HEX NYBLE ASCII - Convert hex digit (4 bits) to 1 ASCII display byte ;
  1039. ;------------------------------------------------------------------------------;
  1040. ;Input: AH upper 4 bits contain hex to be converted. DI points to output record;
  1041. ;       DX should be set to zero for leading zero suppression.                 ;
  1042. ;Output: 1 byte in output record will contain ASCII display code of HEX byte.  ;
  1043. ;       AH be shifted 4 bits to left. AL will contain ASCII version of HEX.    ;
  1044. ;       DI will be incremented twice. DX will be = SP if nonzero output        ;
  1045. ;------------------------------------------------------------------------------;
  1046. Convert_Hex_Nyble_ASCII:
  1047.         XOR     AL,AL                     ;Zero out AL
  1048.         ROL     AX,1                      ;Move half byte (hex digit) into AL
  1049.         ROL     AX,1
  1050.         ROL     AX,1
  1051.         ROL     AX,1                      ;AL now contains a hex digit
  1052.         OR      AL,AL                     ;Is this a zero?
  1053.         JE      Leading_Zero_check        ;If so check if this is leading zero
  1054.         MOV     DX,SP                     ;Set non 0 to indicate non 0 found
  1055. Continue_hex_check:
  1056.         CMP     AL,9                      ;Is digit 0 to 9 or A to F ?
  1057.         JA      Hex_alpha_digit           ;If hex A to F, do special conversion
  1058.         ADD     AL,'0'                    ;Convert hex digit to ASCII display
  1059.         STOSB                             ;store in display field (Out_F_size)
  1060.         RET
  1061. Hex_alpha_digit:                          ;Convert hex A to F to ASCII display
  1062.         ADD     AL,'A'-10
  1063.         STOSB                             ;store in display field (Out_F_size)
  1064.         RET
  1065. Leading_Zero_Check:                       ;Check and blank out leading zeros
  1066.         OR      DX,DX                     ;Have non zeros been detected yet?
  1067.         JNZ     Continue_hex_check        ;If so then do normal processing
  1068.         MOV     AL,' '                    ;Else put out a leading blank
  1069.         STOSB
  1070.         RET
  1071.  
  1072.  
  1073. ;------------------------------------------------------------------------------;
  1074. ;   CONVERT DEC ASCII   -  Convert 2 decimal digits to 2 ASCII display bytes   ;
  1075. ;------------------------------------------------------------------------------;
  1076. ;Input: BL contains 10. AX contains decimal number 0 to 99 to be converted.    ;
  1077. ;       DI points to destination to store result                               ;
  1078. ;Output: AH will have lower decimal ASCII digit and AL uppper digit.           ;
  1079. ;       Both digits will be stored at location pointed to by DI.               ;
  1080. ;------------------------------------------------------------------------------;
  1081. Convert_DEC_ASCII:
  1082.         DIV     BL                        ;Divide by 10
  1083.         ADD     AX,'00'                   ;Convert to ASCII digits
  1084.         STOSW
  1085.         RET
  1086.  
  1087. ;---------------------------------------------------------------------------;
  1088. ; Report File errors  - General purpose error presenter used by             ;
  1089. ;   the specific error subroutines such as file_size_error + read_error.    ;
  1090. ;   Stack contains the END and (LOC) start of the filespec where error was  ;
  1091. ;   DX = offset to error msg, CX has length of message                      ;
  1092. ;   SI = contains DOS terminate code with specific ERRORLEVEL in lower part ;
  1093. ;---------------------------------------------------------------------------;
  1094. Report_File_errors:                       ;General purpose error display routine
  1095.                                           ;DOS term func + errlvl must be in SI
  1096.         MOV     AX,CS                     ;Point ES back
  1097.         MOV     ES,AX                     ;              to normal data segment
  1098.         MOV     AH,40h                    ;DOS Write func
  1099.         MOV     BX,1                      ;Handle for std output device
  1100.         INT     21h                       ;Write beginning of open error message
  1101.         ADD     SP,2                      ;Remove return address from stack
  1102.         POP     BP                        ;Get starting offset of filespec
  1103.         POP     DI                        ;1 character after end of filespec
  1104.         MOV     AX,CRLF                   ;Terminate file name with CR,LF
  1105.         STOSW
  1106.         SUB     DI,BP                     ;Calc filename length + 2 for CRLF
  1107.         MOV     CX,DI
  1108.         MOV     DX,BP                     ;Start of file name to output
  1109.         MOV     AH,40h                    ;DOS Write func
  1110.         INT     21h
  1111.         CALL    Page_Wait                 ;Beep and force user to hit a key
  1112.         MOV     AX,SI                     ;SI contains 4Ch with error lvl
  1113.         INT     21h
  1114.  
  1115. ;---------------------------------------------------------------------------;
  1116. ; PAGE CONTROL:       (and *PAGE WAIT*   alternate entry point)             ;
  1117. ;  Called only if user specified /P option (BH will be not = to FFh).       ;
  1118. ;  Page control will increment the line counter and pause every 24 lines    ;
  1119. ;  giving the user a prompt to -Hit any KEY -                               ;
  1120. ;ENTRY:                                                                     ;
  1121. ;   AL contains number of lines waiting to be displayed.                    ;
  1122. ;   BH contains line count for this page already.                           ;
  1123. ;   DS points to normal data segment (=CS)                                  ;
  1124. ;EXIT:                                                                      ;
  1125. ;   BH contains updated line count which is reset if page wait happened     ;
  1126. ;---------------------------------------------------------------------------;
  1127. ;PAGE WAIT - Alternate entry point                                          ;
  1128. ;          - simply puts out -HIT ANY KEY- message and waits for user       ;
  1129. ;            to hit any key.                                                ;
  1130. ;---------------------------------------------------------------------------;
  1131. Page_control:
  1132.         ADD     BH,AL                     ;Increment line counter
  1133.         CMP     BH,24                     ;Are we over one page of output?
  1134.         JA      Page_Wait                 ;   If over 1 page then do page wait
  1135.         RET
  1136.  
  1137. Page_Wait:                                ;Alternate entry point (here)
  1138.         MOV     BH,AL                     ;Reset the line counter
  1139.  
  1140.         PUSH    BP                        ;Save all corrupted registers
  1141.         PUSH    BX
  1142.         PUSH    CX
  1143.         PUSH    DI
  1144.         PUSH    DX
  1145.         PUSH    SI
  1146. ; Produce a beep to alert the user:  (use  BIOS TTY func to write an ASCII BELL)
  1147.         MOV     AX,0E07h                  ;BIOS func (0Eh) to write (07H) beep
  1148.         XOR     BH,BH                     ;Select page zero for output
  1149.         INT     10h                       ;BIOS video function (0Eh=write char)
  1150.  
  1151. ;Find out what attribute is being used for display
  1152.         MOV     AH,08h                    ;read attrib + char function
  1153.         INT     10h                       ;Call BIOS
  1154.         PUSH    AX                        ;Save AH=attribute byte
  1155.  
  1156. ;Find out what line the cursor is on
  1157.         MOV     AH,03h                    ;Read cursor position function
  1158.         INT     10h                       ;BIOS video services
  1159.         PUSH    DX                        ;DH contains row (line #) Save it!
  1160.  
  1161.  
  1162. ; Position cursor to current line + column 28: (TO BIOS  row 27)
  1163.         MOV     AH,02                     ;BIOS int 10h set cursor position func
  1164.         XOR     BH,BH                     ;Set page to zero
  1165.                                           ;DH contains current row
  1166.         MOV     DL,1Bh                    ;Set cursor current row and col 27
  1167.         INT     10h                       ;BIOS video services
  1168.  
  1169. ; Put -Hit any key- message out with inverse video attribute type on
  1170. ;       XOR     BH,BH                     ;Set page to zero  (BH is still 0)
  1171.         MOV     BL,0F0h                   ;Inverse video attribute
  1172.         MOV     CX,1                      ;Character count
  1173.         MOV     SI,offset Hit_Key_Msg     ;The hit-any-key message
  1174. Display_next_video_char:
  1175.         MOV     AH,09h                    ;BIOS int 10h write attrib + char func
  1176.         LODSB                             ;Get next character for output
  1177.         PUSH    SI                        ;Save SI (int 10h may corrupt it)
  1178.         INT     10h                       ;Put character and attribute out
  1179.         INC     DX                        ;Advance cursor position
  1180.         MOV     AH,02                     ;Adv cursor function
  1181.         INT     10h                       ;   advance the cursor (BIOS)
  1182.         POP     SI                        ;Restore saved SI
  1183.         CMP     SI,offset Hit_key_Msg_end ;are we at end of message?
  1184.         JB      Display_next_video_char   ;  If not get next char for display
  1185.                                           ;  Else, wait for key press by user
  1186. ; Wait for user to hit any key
  1187.         XOR     AX,AX
  1188.         INT     16h                       ;Wait for user to hit a key
  1189.  
  1190. ; Erase HIT ANY KEY message
  1191.         POP     DX                        ;DH=current line number
  1192.         POP     BX                        ;BH=user's screen attribute
  1193.         MOV     AH,06h                    ;INIT window function
  1194.         XOR     AL,AL                     ;Zero AL to clear window
  1195.         MOV     CH,DH                     ;Current row (y coor upr lft)
  1196.         MOV     CL,00                     ;Start in first char position
  1197.         MOV     DL,79                     ;Last char pos - blank entire line
  1198.         INT     10h                       ;Blank out line
  1199.  
  1200. ; Position cursor to start of blanked line
  1201.         MOV     AH,02                     ;BIOS int 10h set cursor position func
  1202.         XOR     DL,DL                     ;DH=cur line, DL=0: first char pos
  1203.         XOR     BX,BX                     ;Use video page zero
  1204.         INT     10h                       ;BIOS video services
  1205.  
  1206.         POP     SI                        ;Restore all corrupted registers
  1207.         POP     DX
  1208.         POP     DI
  1209.         POP     CX
  1210.         POP     BX
  1211.         POP     BP
  1212.         RET                               ;Return to caller
  1213.  
  1214.  
  1215. ;---------------------------------------------------------------------------;
  1216. ; PRINT HEADER Msg - Displays column headers the first time CFCOMPC decides ;
  1217. ;     it needs to display a changed record.                                 ;
  1218. ;ENTRY:                                                                     ;
  1219. ;   DS points to normal data segment (=CS)                                  ;
  1220. ;EXIT:                                                                      ;
  1221. ;   DX,CX,AX are corrupted.                                                 ;
  1222. ;---------------------------------------------------------------------------;
  1223. Print_Header_Msg:
  1224.         PUSH    BX                        ;Save BX
  1225.         MOV     BX,1                      ;Write to STD output device (=1)
  1226.         MOV     DX, offset Header_Msg     ;beginning loc of directory string
  1227.         MOV     CX,179                    ;182 chars in header message
  1228.         MOV     AH,40h                    ;DOS write
  1229.         INT     21h
  1230.         POP     BX
  1231.         RET
  1232.         SUBTTL  Definition of Data structures
  1233.         PAGE
  1234. ;******************************************************************************;
  1235. ;**   Definition of Data areas follow                                        **;
  1236. ;******************************************************************************;
  1237. File_Size_PARAs      DW   1000h           ;Size of each REP file in paragraphs
  1238. File_Size_Bytes      DW   0FFFFh          ;Size of each REP file in bytes
  1239. OLD_Filename_Loc     DW   0               ;offset of filespec for OLD file
  1240. OLD_Filename_end     DW   0               ;end of filespec for OLD report file
  1241. OLD_File_Handle      DW   0               ;File handle  for OLD report file
  1242. OLD_Rec_count        DW   0               ;Number of 25 char report recs on file
  1243. OLD_Tot_Loc          DW   0               ;Offset of CHKSUM on totals records
  1244. NEW_Filename_Loc     DW   0               ;offset of filespec for NEW file
  1245. NEW_Filename_end     DW   0               ;end of filespec for NEW report file
  1246. NEW_File_Handle      DW   0               ;File handle for NEW report file
  1247. NEW_Rec_count        DW   0               ;Number of 25 char report recs on file
  1248. NEW_Tot_Loc          DW   0               ;Offset of CHKSUM on totals records
  1249. NEW_End_Of_File      DW   0               ;Offset 1st chr past last 25 chr rec
  1250. Changes_Only         DB   0               ;="Y" if user wants only changes
  1251. Missing_Old_File     DB   0               ;="Y" if OLD report file not found
  1252. Page_Mode            DB   0FFh            ;=00h  means stop after each page
  1253. File_Open_Err_Msg    DB  'Open fail'
  1254. File_Read_Err_Msg    DB  'Read fail'
  1255. Mem_Err_Msg          DB   'Error in MEM ALLOC'
  1256. CRLF_Msg             DB   CR,LF,'$'
  1257. Mem_loss_Msg         DB   'Memory lack limits file size'
  1258.                      DB   CR,LF,'$'
  1259. Read_Err_Msg         DB   'Error reading: '
  1260. Type_Err_Msg         DB   'Wrong type of file: '
  1261.                      DB   CR,LF
  1262. Size_Err_Msg         DB   'File size too large: '
  1263. CHGD_Msg_1           DB   'Chgd: OLD:'
  1264. CHGD_Msg_2           DB   '      NEW:'
  1265. Deleted_Msg          DB   'Deleted-->'
  1266. Added_Msg            DB   'NEW Fil-->'
  1267. Tot_match_Msg        DB   'File totals match',CR,LF
  1268. Tot_nomatch_Msg      DB   'File totals unequal',CR,LF
  1269. Hit_Key_Msg          DB   '-Hit any key-'
  1270. Hit_Key_Msg_end      EQU $
  1271. Header_Msg  DB  '          File Name + Check Check  File    Update   Update'
  1272.             DB   CR,LF
  1273.             DB  '          Extension:  Val1: Val2:  Size:   Date:    Time:'
  1274.             DB   CR,LF
  1275.             DB  '          ----------   ---- ----   -----   ------   ------'
  1276.             DB   CR,LF
  1277.  
  1278.  
  1279. ;******************************************************************************;
  1280. ;**   Definition of DSP (Display) file record:                               **;
  1281. ;** This is the record description of individual check records for output.   **;
  1282. ;** These records are expanded versions read from the new + old report files **;
  1283. ;******************************************************************************;
  1284. DSP_Rec       EQU  $                      ;Name for the entire display record
  1285. DSP_F_Name    DB   12 DUP (' ')           ;12 spaces reserved for filename
  1286.               DB   ' '
  1287. DSP_CHK_Sum   DB   4  DUP ('0')           ;Check value 1: 4 hex digits
  1288.               DB   ' '
  1289. DSP_XOR_Sum   DB   4  DUP ('0')           ;Check value 2: 4 hex digits
  1290.               DB   ' '
  1291. DSP_F_Size    DB   8 DUP ('0')            ;Size of file: 8 Hex digits
  1292.               DB   ' '
  1293. DSP_F_MM      DB   'MM'                   ;Date of last file update:
  1294.               DB   '/'
  1295. DSP_F_DD      DB   'DD'
  1296.               DB   '/'
  1297. DSP_F_YY      DB   'YY'
  1298.               DB   ' '
  1299. DSP_F_HH      DB   'HH'                   ;Time of last file update
  1300.               DB   ':'
  1301. DSP_F_MI      DB   'MI'                   ;MInutes
  1302.               DB   ':'
  1303. DSP_F_SS      DB   'SS'
  1304.               DB   CR,LF                  ;End of DSP_Rec (display record) desc
  1305.  
  1306.  
  1307.         SUBTTL  INIT data + code (also input BUFFERs + stack)
  1308. ;******************************************************************************;
  1309. ;**   Definition of file buffer Data areas and code follow:                  **;
  1310. ;** All the following storage will be overlaid when records are read in      **;
  1311. ;******************************************************************************;
  1312.  
  1313.               EVEN
  1314. Buffer_area   label  byte                 ;All storage + code following is in
  1315.                                           ; the input file buffer.
  1316.  
  1317. ; ----------------------------------------------------------------------------;
  1318. ; Initialization code - parse parms + put out msgs and open both files        ;
  1319. ; ----------------------------------------------------------------------------;
  1320. Parse_Parms_Open_Files:                   ;Parse input parameters + displ header
  1321.         MOV     SI,80h                    ;Parameter area in PSP
  1322.         MOV     CL,[SI]                   ;Get # of chars in input parm
  1323.         XOR     CH,CH                     ;Clear upper byte of char count
  1324.         INC     SI                        ;Point to first char
  1325.  
  1326. ;---------------------------------------------------------------------------;
  1327. ; Conventions for command line parsing:                                     ;
  1328. ;   SI points to next char to be checked in the parm field at DS:80         ;
  1329. ;   CX is count of characters left to be scanned                            ;
  1330. ;   BP points to start of current processed filespec.                       ;
  1331. ;---------------------------------------------------------------------------;
  1332.  
  1333.         Call    Parse_Filespec            ;exract 1st filespec from parm area
  1334.         CMP     AL,'/'                    ;Is the file separator char a "/"?
  1335.         JNE     Filespec1_OK              ;  If its not an early parm ("/")
  1336.         JMP     No_File_Exit              ;  Display error + correct syntax
  1337. Filespec1_OK:
  1338.         MOV     OLD_Filename_Loc,BP       ;Store location of file name
  1339.         MOV     OLD_Filename_end,DI       ;Store char loc after end of filespec
  1340. ;       Adjust CX to reflect actual characters left to be scanned
  1341.         JCXZ    Skip_decrement            ;Don't decrement CX if already = 0
  1342.         DEC     CX
  1343. Skip_decrement:
  1344.         Call    Parse_Filespec            ;extract 2nd filespec from parm area
  1345.         MOV     NEW_Filename_Loc,BP       ;Store location of 2nd file name
  1346.         MOV     NEW_Filename_end,DI       ;Store char loc after end of filespec
  1347.  
  1348.         CALL    Parse_parms               ;Process any "/" parms
  1349.         CALL    Put_Out_Initial_MSGs      ;Display start messages
  1350.  
  1351.         MOV     DX,OLD_Filename_Loc       ;Open the first ("OLD") file
  1352.         MOV     AX,3D00h                  ;DOS open file (handle) for read cmnd
  1353.         INT     21h                       ;invoke DOS
  1354.         JNC     Continue_Open             ;If no errors continue processing
  1355.  
  1356. ;       If open fails for OLD file, treat it as if file were empty - keep going
  1357.         MOV     Missing_Old_File,'Y'      ;Else, Indicate old file was gone
  1358.         MOV     DI,OLD_Filename_end
  1359.         CALL    File_Open_Error           ;Put out file open error message
  1360.         MOV     DX, OFFSET Empty_OLD_Msg  ;Tell user we will pretend file is MT
  1361.         MOV     AH,09h                    ;DOS display string function
  1362.         INT     21h
  1363.  
  1364. Continue_Open:
  1365.         MOV     OLD_File_handle,AX        ;Save DOS file handle
  1366.         MOV     DX,NEW_Filename_Loc       ;Open the 2nd (AKA "NEW") file
  1367.         MOV     AX,3D00h                  ;DOS open file (handle) for read cmnd
  1368.         INT     21h                       ;invoke DOS
  1369.         JNC     Open_done                 ;If no errors continue processing
  1370.         MOV     DI,NEW_Filename_end
  1371.         CALL    File_Open_Error           ;Put out file open error message
  1372.         CALL    Page_Wait                 ;Beep and force user to hit a key
  1373.         MOV     AX,4C14h                  ;   terminate with 20 error level
  1374.         INT     21h
  1375. Open_done:
  1376.         MOV     NEW_File_handle,AX        ;Save DOS file handle
  1377.         RET
  1378.  
  1379. ;---------------------------------------------------------------------------;
  1380. ; Parse filespec:                                                           ;
  1381. ; Input:                                                                    ;
  1382. ;   SI points to next char to be checked in the parm field at DS:80         ;
  1383. ;   CX is count of characters left to be scanned                            ;
  1384. ;                                                                           ;
  1385. ; Returns:                                                                  ;
  1386. ;   AL contains final separator found at end of filespec (if any).          ;
  1387. ;   BP points to start of filespec                                          ;
  1388. ;   DI points to byte after last char in filespec                           ;
  1389. ;   Filespec is zero terminated in the parameter area                       ;
  1390. ;---------------------------------------------------------------------------;
  1391. Parse_Filespec:                           ;Extract and zero terminate filename
  1392.         OR      CL,CL                     ;Check for 0 chars (NO INPUT)
  1393.         JZ      No_File_Exit              ;If no parms, put out error msg
  1394.  
  1395. DEL_SPACES:                               ;Get rid of extra spaces
  1396.         LODSB                             ;Get byte at DS:SI and inc SI
  1397.         CMP     AL,' '                    ;Is it a space?
  1398.         JNE     Set_File_name             ;If not, we should have a file name..
  1399.         LOOP    DEL_SPACES                ;Cont checking unitl last char
  1400.  
  1401. No_File_Exit:                             ;For no input, explain syntax to user:
  1402.         MOV     DX, OFFSET NO_FILE_Msg    ;Prepare error message
  1403.         MOV     AH,09h                    ;DOS display string function
  1404.         INT     21h
  1405.         JMP     SHORT Give_Syntax_and_Quit ;Give user correct syntax + Termn
  1406.  
  1407. ;--------------------------------------------;
  1408. ; Parse file spec and zero byte terminate it ;
  1409. ;--------------------------------------------;
  1410. Set_File_Name:
  1411.         DEC     SI                        ;point back to 1ST letter of filespec
  1412.         MOV     BP,SI                     ;Save a copy of filespec start
  1413.  
  1414. Scan_To_File_Spec_End:
  1415. ;       start scanning the file specification and transfer into output field
  1416.         LODSB                             ;Get next char of file spec
  1417.         CMP     AL,' '                    ;check valid separator character
  1418.         JBE     file_spec_end_found
  1419.         CMP     AL,'/'                    ;check for valid separator
  1420.         JE      file_spec_end_found
  1421.         CMP     AL,','                    ;check for valid separator
  1422.         JE      file_spec_end_found
  1423.         LOOP    Scan_To_File_Spec_End
  1424.         INC     SI                        ;Adjust SI if no separator char found
  1425.  
  1426. File_Spec_End_Found:
  1427. ;       SI is pointing 2 characters past end of filespec at this time
  1428.         MOV     DI,SI
  1429.         DEC     DI                        ;DI points to 1st char after filespec
  1430.         MOV     BYTE PTR [DI],00          ;zero terminate the filespec: ASCIIZ
  1431.         RET
  1432.  
  1433. ;----------------------------------------------------------------;
  1434. ;   Parse Parms:     parse /P and /C parameters                  ;
  1435. ;   Input:    SI must point to next character to process         ;
  1436. ;             CX contains # of chars left in paramter area       ;
  1437. ;----------------------------------------------------------------;
  1438. Parse_Parms:
  1439. Check_parm_chars_left:                    ;Check if enough chars left for a parm
  1440.         CMP     CX,01                     ;Check if no more chars to scan
  1441.         JA      Parm_Scan                 ;   If Not, continue checking
  1442.         RET                               ;   If no more chars, we are done
  1443. Parm_Scan:                                ;Check for presence of a /_ parm
  1444.         CMP     AL,'/'                    ;check for "/" parm character
  1445.         JE      Parm_found
  1446.         CMP     AL,' '                    ;Check for blanks
  1447.         JNE     Unrecog_parm              ;If other than blank its illegal...
  1448.         LODSB                             ;Keep checking next character
  1449.         LOOP    Parm_Scan
  1450.         RET                               ;Finished (parsing parms)
  1451.  
  1452. Parm_Found:                               ;Check if parm is valid
  1453.         DEC     CX                        ;Adjust chars remaining counter
  1454.         JCXZ    Unrecog_parm              ;IF no chars left then parm is invalid
  1455.         LODSB                             ;Get next char
  1456.         DEC     CX                        ;Adjust chars remaining counter
  1457.         AND     AL,5Fh                    ;Capitalize char
  1458.         CMP     AL,'P'                    ;Is it the "Totals wanted" parm?
  1459.         JE      P_parm                    ;T parameter detected
  1460.         CMP     AL,'C'                    ;Is it alternate Check Sum parm?
  1461.         JE      C_parm                    ;C parameter detected..
  1462.         CMP     AL,'O'                    ;Is it "Only chk field compare parm"?
  1463.         JE      O_parm                    ;C parameter detected..
  1464. Unrecog_parm:                             ; an illegal parameter:
  1465.         MOV     DX, offset Bad_Parm_Msg   ;indicate illegal parm was found
  1466.         MOV     AH,09h                    ;DOS display string function
  1467.         INT     21h
  1468. Give_Syntax_and_Quit:
  1469.         CALL    Page_Wait                 ;Beep and force user to hit a key
  1470.         MOV     DX, offset Syntax_Msg     ;Give user the correct syntax
  1471.         MOV     AH,09h                    ;DOS display string function
  1472.         INT     21h
  1473.         MOV     AX,4C80h                  ;   terminate with 128 error level
  1474.         INT     21h
  1475.  
  1476. P_parm:
  1477.         MOV     Page_Mode,03h             ;Indicate user wants page mode
  1478.                                           ;Std out already has 3 line header
  1479.                                           ;Originally =FFh to turn page mode off
  1480.         LODSB                             ;Keep checking next character
  1481.         JMP     SHORT Check_Parm_chars_left     ;Check for additional parms
  1482.  
  1483. C_parm:
  1484.         MOV     Changes_Only,'Y'          ;User wants only changes (no add/del)
  1485.         LODSB                             ;Keep checking next character
  1486.         JMP     SHORT Check_Parm_chars_left     ;Check for additional parms
  1487.  
  1488. O_parm:                                   ;Compare only Check fields
  1489. ; IF the /O option is selected, we will patch the length field of two
  1490. ; MOV CX,06 instructions in the COMPARE_FILES subroutine labeled PATCH1 and
  1491. ; PATCH2. These instructions will then only compare 4 words (the CHECK fields
  1492. ; and file size) rather than the entire remaining record.
  1493.         MOV     BYTE PTR[PATCH1+1],04     ;Patch length field of MOV CX instr
  1494.         MOV     BYTE PTR[PATCH2+1],04     ;Patch length field of MOV CX instr
  1495.         LODSB                             ;Keep checking next character
  1496.         JMP     SHORT Check_Parm_chars_left     ;Check for additional parms
  1497.  
  1498.  
  1499. ;----------------------------------------------------------------;
  1500. ;   File Open Error - put out file open error message + terminate;
  1501. ;   Input:    DX must point to start of filespec                 ;
  1502. ;             DI must point to end of filespec                   ;
  1503. ;----------------------------------------------------------------;
  1504. File_Open_Error:
  1505.         PUSH    DX                        ;Save filename
  1506.         MOV     DX, offset Open_Err_Msg   ;Indicate open failed
  1507.         MOV     CX,24                     ;Length of msg is 24 chars
  1508.         MOV     AH,40h                    ;DOS Write func
  1509.         MOV     BX,1                      ;Handle for std output device
  1510.         INT     21h                       ;Write beginning of open error message
  1511.         POP     DX                        ;restore name of file loc to DX
  1512.         SUB     DI,DX                     ;Calc length of filename
  1513.         MOV     CX,DI                     ;CX contains file length
  1514.         MOV     AH,40h                    ;DOS Write func
  1515.         INT     21h
  1516.         MOV     DX,OFFSET CRLF_Msg        ;Put out a carriage return line-feed
  1517.         MOV     AH,09h                    ;DOS display string func
  1518.         INT     21h
  1519.         RET
  1520.  
  1521. Put_Out_Initial_MSGs:                     ;Display header and start messages
  1522.         MOV     DX, offset Start_Msg      ;beginning of start message
  1523.         MOV     CX,SM_end-Start_MSG       ;Start message begins with 61 chars
  1524.         MOV     AH,40h                    ;DOS Write func
  1525.         MOV     BX,1                      ;Handle for std output device
  1526.         INT     21h                       ;Write Start message
  1527.  
  1528.         MOV     SI,offset Start_Dir       ;Place to store current  directory
  1529.         XOR     DL,DL                     ;Zero DL in order to use default drive
  1530.         MOV     AH,47h                    ;Get current directory (path) func
  1531.         INT     21h
  1532.         CLD                               ;Scan in forward direction
  1533.         MOV     DI,offset Start_Dir       ;Scan dir strng to determine length
  1534.         XOR     AX,AX                     ;Scan for zero termination of dir
  1535.         MOV     CX,64                     ;Scan up to 64 chars of directory
  1536.         REPNE   SCASB                     ;Find 1st zero byte
  1537.         MOV     AX,CRLF
  1538.         STOSW                             ;Terminate dir string with CR LF
  1539.         MOV     DX, offset Start_Dir      ;Beginning loc of directory string
  1540.         SUB     DI,SI                     ;Calc length of directory string
  1541.         MOV     CX,DI                     ;Length reg for DOS write function
  1542.         MOV     AH,40h                    ;DOS Write func
  1543.         INT     21h                       ;Write Dir string to finish start msg
  1544.         RET
  1545.  
  1546. ; --------------------------------------------------;
  1547. ; Initialization DATA STORAGE                       ;
  1548. ; --------------------------------------------------;
  1549. Start_MSG     DB  CR,LF,"CFCOMPC 1.0 ",BOX," PCDATA TOOLKIT (c) 1990"
  1550.               DB  " Ziff Communications Co.",CR,LF
  1551.               DB  "PC Magazine ",BOX," Wolfgang Stiller - In directory: \"
  1552. SM_End        LABEL  BYTE     ;End of the Start message
  1553. Start_Dir     DB   66  DUP (0)
  1554. Open_ERR_Msg  DB  'CFCOMPC unable to open: '
  1555. Empty_Old_Msg DB  'OLDfile assumed empty - execution continues.',CR,LF,'$'
  1556. Bad_Parm_Msg  DB  'Unrecognized parameter detected.',CR,LF,LF,'$'
  1557. NO_FILE_Msg   DB  'You must specify at least OLD and NEW file names to compare.'
  1558.               DB   CR,LF,'$'
  1559.  
  1560. Syntax_Msg    DB  "CFCOMPC 1.0 ",BOX," PCDATA TOOLKIT Copyright (c) 1990"
  1561.               DB  " Ziff Communications Co.",CR,LF
  1562.               DB  "PC Magazine ",BOX," Wolfgang Stiller",CR,LF
  1563.               DB  CR,LF,'CFCOMPC does a high speed compare of the compressed'
  1564.               DB ' report files produced',CR,LF
  1565.               DB 'by CHKfileC.  It displays all changes between the OLD and '
  1566.               DB 'NEW report files.',CR,LF,LF
  1567.               DB 'Syntax is: CFCOMPC OLDfile NEWfile  [/C] [/O] [/P]'
  1568.               DB   CR,LF,LF
  1569.               DB  '  OLDfile and NEWfile are files created by CHKFILEC.COM.'
  1570.               DB  CR,LF,LF
  1571.               DB  '  "/C"    Display only changed files not additions or '
  1572.               DB  'deletions.',CR,LF
  1573.               DB  '  "/O"    Only use check fields and file size in comparing '
  1574.               DB  'files.'
  1575.               DB  CR,LF
  1576.               DB  '          DOS time and Date stamps are not used for compare.'
  1577.               DB  CR,LF
  1578.               DB  '  "/P"    Pause between pages if changes found.'
  1579.               DB   CR,LF,'$'
  1580. CSEG    EndS
  1581.         END     CFCOMPC
  1582.